package gotnames.web.st;

import gotnames.Utils;
import gotnames.dm.Group;
import gotnames.dm.ProfilePicture;
import gotnames.dm.QueryBuilder;
import gotnames.dm.User;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;

import com.medallia.spider.Task;
import com.medallia.tiny.CollUtils;
import com.medallia.tiny.Empty;
import com.medallia.tiny.Encoding;
import com.medallia.tiny.Func;
import com.medallia.tiny.Funcs;
import com.medallia.tiny.Strings;

/**
 * Task which generates a .zip file containing a 'Users.csv' file with a list of
 * everyone in the group as well as one .jpg file for each user with a profile
 * picture. It is linked to from {@link AdminTask} and {@link UploadArchiveTask}
 * can be used to upload the .zip file after making modifications to it.
 */
public class DownloadArchiveTask extends Task {
	
	PostAction action(User user, PersistenceManager pm) {
		if (!user.isAdmin())
			return redirectToTask(GuessNamesTask.class);
		
		final String groupName = QueryBuilder.begin(pm, Group.class).getSingleByKey(user.getGroupKey()).getName();
		
		Query q = pm.newQuery(User.class);
		q.setFilter("groupKey == " + user.getGroupKey());
		q.setOrdering("firstName ASC, lastName ASC");
		
		final Collection<User> users = Utils.<Collection<User>>cast(q.execute());
		List<String> lines = Funcs.map(users, new Func<User, String>() {
			@Override public String call(User u) {
				List<String> l = Empty.list();
				l.add(u.getFirstName());
				l.add(u.getLastName());
				l.add(u.getEmail());
				l.add(u.getGender().toString());
				l.add(Boolean.toString(u.isDisableEmail()).toLowerCase());
				l.add(Boolean.toString(u.isAdmin()).toLowerCase());
				
				return Strings.join("\t", l);
			}
		});
		
		// add header
		lines = CollUtils.concat(Collections.singleton(Strings.join("\t", Arrays.asList(
			"First name", "Last name", "Email", "Gender", "No email", "Admin"
		))), lines);
		
		final String excel = Strings.join("\n", lines);
		
		final Map<Long, ProfilePicture> profilePictureByUserKey =
			Funcs.buildMap(QueryBuilder.begin(pm, ProfilePicture.class).getAllByKey("userKey", Funcs.map(users, User.KEY_FUNC)), ProfilePicture.USER_KEY_FUNC);
		
		return new BinaryDataPostAction() {
			@Override protected String getContentType() {
				return "application/zip";
			}
			@Override public void respond(HttpServletRequest req, HttpServletResponse res) throws IOException {
				res.setHeader("Content-Disposition", String.format("attachment; filename=GotNames-%s-Users.zip", groupName));
				super.respond(req, res);
			}
			@Override protected void writeTo(OutputStream out) throws IOException {
				ZipOutputStream zo = new ZipOutputStream(out);
				
				// Write csv file
				zo.putNextEntry(new ZipEntry("Users.csv"));
				OutputStreamWriter usersOut = new OutputStreamWriter(zo, Encoding.CHARSET_UTF8);
				IOUtils.copy(new StringReader(excel), usersOut);
				usersOut.flush();
				zo.closeEntry();
				
				// Write profile pictures
				for (User u : users) {
					ProfilePicture pp = profilePictureByUserKey.get(u.getKey());
					if (pp != null) {
						zo.putNextEntry(new ZipEntry(u.getFullName() + ".jpg"));
						IOUtils.copy(new ByteArrayInputStream(pp.getPicture().getBytes()), zo);
						zo.closeEntry();
					}
				}
				zo.close();
			}
		};
	}

}
